package dkbta.ontology.elements.event;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import dkbta.ontology.Ontology;
import dkbta.ontology.elements.ElementDef;
import dkbta.ontology.elements.ElementType;
import dkbta.ontology.loading.OntologyException;
import dkbta.ontology.values.ScaledValues;
import dkbta.ontology.values.Values;
import dkbta.processing.Patient;

/**
 * Represents an Event with attributes
 * 
 * @author Uri Kanonov
 */
public class EventDef extends ElementDef{
	/** The event's attributes */
	private final LinkedHashMap<String, ScaledValues> _attributes;

	/**
	 * Initializes an Event
	 * 
	 * @param name The element's name
	 * @param componentType The element's component type
	 * @param attributes The attributes this event has
	 */
	public EventDef(String name, String componentType,
		LinkedHashMap<String, ScaledValues> attributes){
		super(ElementType.EVENT, name, componentType, null);
		_attributes = attributes;
	}

	@Override
	public void validate(Ontology ontology) throws OntologyException{
		// Created Events are always valid
	}

	/**
	 * Retrieves the values of an attribute of the event
	 * 
	 * @param attributeName The name of attribute
	 * @return The values of the attribute corresponding to the given name
	 */
	public ScaledValues getAttributeValues(String attributeName){
		return _attributes.get(attributeName);
	}

	@Override
	public String completeToString(){
		StringBuilder sb = new StringBuilder(super.completeToString());
		if (!_attributes.isEmpty()){
			sb.append("Attributes: ");
			for (Map.Entry<String, ScaledValues> attr : _attributes.entrySet()){
				sb.append("\r\n\t").append(attr.getKey()).append(" , ").append(
					attr.getValue());
			}
		}
		sb.append("\r\n");
		return sb.toString();
	}

	@Override
	public Event newInstance(long startTime, long endTime, String[] values){
		if (values.length != _attributes.size()){
			throw new IllegalArgumentException("The given event info has "
					+ values.length + " attributes instead of " + _attributes.size());
		}

		Map<String, EventAttribute> attributeValues = null;

		if (!_attributes.isEmpty()){
			attributeValues = new LinkedHashMap<String, EventAttribute>();
			int index = 0;

			// Relying on the fact that the linked hashmap's iterator
			// traverses the elements in the insertion order. i.e. the order
			// they were defined in the ontology
			for (Map.Entry<String, ScaledValues> attr : _attributes.entrySet()){
				Values attrValues = attr.getValue().getValues();
				String attrName = attr.getKey();
				String rawValue = values[index++];
				Object validatedValue = attrValues.parseAndValidate(rawValue);

				if (validatedValue == null){
					throw new IllegalArgumentException("Invalid value + '" + rawValue
							+ "' for the attribute + " + attrName + " with the values: "
							+ attrValues);
				}

				attributeValues.put(attrName, new EventAttribute(validatedValue,
						attrValues.getValueType()));
			}
		}
		return new Event(_name, startTime, endTime, attributeValues);
	}

	@Override
	public void addRequiredPrimsAndEvents(Set<ElementDef> requiredPrimsAndEvents){
		requiredPrimsAndEvents.add(this);
	}

	@Override
	public void compute(Patient p){
		throw new UnsupportedOperationException("Events aren't meant to be computed");
	}
}
